import hashlib
import json
import logging
import time
import urllib.parse
from typing import Dict, Any, Union

import requests


class JiKeYunAPIClient:
    """
    吉客云开放平台API客户端
    """

    def __init__(self, app_key: str = "12540443", app_secret: str = "a7860451c1b6470da900bd40d91addb2"):
        """
        初始化API客户端
        :param app_key: 应用的AppKey，默认为12540443
        :param app_secret: 应用的AppSecret，默认为a7860451c1b6470da900bd40d91addb2
        """
        self.app_key = app_key
        self.app_secret = app_secret
        self.api_url = "https://open.jackyun.com/open/openapi/do"

    def send_request(self, method: str, bizdata: Union[Dict, str]) -> Dict[str, Any]:
        """
        向吉客云开放平台发送API请求。
        :param method: API接口名称
        :param bizdata: 业务请求参数（字典或JSON字符串）
        :return: API响应
        """
        try:
            # 1. 准备用于签名的系统级参数
            bizcontent_str = json.dumps(bizdata, ensure_ascii=False) if isinstance(bizdata, dict) else str(bizdata)
            params_for_sign = {
                'method': method,
                'appkey': self.app_key,
                'version': '1.0',
                'contenttype': 'json',
                'timestamp': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
                'bizcontent': bizcontent_str
            }

            # 2. 生成签名
            signature = self._generate_signature(params_for_sign)
            params_for_sign['sign'] = signature

            # 3. 准备最终请求体
            post_data_str = self._prepare_request_data(params_for_sign)

            # 4. 发送POST请求
            headers = {
                'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
            }

            response = requests.post(
                self.api_url,
                data=post_data_str.encode('utf-8'),
                headers=headers,
                timeout=30
            )
            response.raise_for_status()

            # 解析响应
            api_response = response.json()

            # 记录响应日志
            try:
                logging.info(f"吉客云API原始响应: {api_response}")
            except (IOError, OSError) as log_error:
                # 日志记录失败，记录到标准错误输出
                print(f"警告：日志记录失败 - {log_error}")

            return api_response

        except requests.exceptions.Timeout:
            logging.error("请求超时")
            return {
                'success': False,
                'code': 'TIMEOUT',
                'message': '请求超时，请稍后重试'
            }
        except requests.exceptions.ConnectionError:
            logging.error("网络连接错误")
            return {
                'success': False,
                'code': 'CONNECTION_ERROR',
                'message': '网络连接失败，请检查网络设置'
            }
        except requests.exceptions.HTTPError as e:
            logging.error(f"HTTP错误: {e}")
            return {
                'success': False,
                'code': f'HTTP_{e.response.status_code}',
                'message': f'HTTP错误: {e.response.status_code}'
            }
        except json.JSONDecodeError:
            logging.error("响应不是有效的JSON格式")
            return {
                'success': False,
                'code': 'INVALID_JSON',
                'message': '服务器响应格式错误'
            }
        except requests.exceptions.RequestException as e:
            logging.error(f"请求出错: {e}")
            return {
                'success': False,
                'code': 'REQUEST_ERROR',
                'message': f'请求失败: {str(e)}'
            }
        except Exception as e:
            logging.error(f"未知错误: {e}", exc_info=True)
            return {
                'success': False,
                'code': 'UNKNOWN_ERROR',
                'message': f'未知错误: {str(e)}'
            }

    def _generate_signature(self, params: Dict[str, Any]) -> str:
        """
        生成API签名
        :param params: 参数字典
        :return: 签名字符串
        """
        sorted_params = sorted(params.items())
        query_string = ""
        for key, value in sorted_params:
            if key and value:
                query_string += f"{key}{value}"
        sign_string = (self.app_secret + query_string + self.app_secret).lower()
        return hashlib.md5(sign_string.encode('utf-8')).hexdigest().lower()

    def _prepare_request_data(self, params: Dict[str, Any]) -> str:
        """
        准备请求数据
        :param params: 参数字典
        :return: URL编码后的请求字符串
        """
        post_data_parts = []
        for key, value in params.items():
            if key == 'bizcontent':
                # 只对bizcontent进行URL编码
                post_data_parts.append(f"{key}={urllib.parse.quote(str(value), safe='')}")
            else:
                post_data_parts.append(f"{key}={str(value)}")
        return "&".join(post_data_parts)


# 为了向后兼容，保留原有的函数接口
def send_request(method: str, bizdata: Union[Dict, str]) -> Dict[str, Any]:
    """
    向吉客云开放平台发送API请求（兼容性函数）
    :param method: API接口名称
    :param bizdata: 业务请求参数（字典或JSON字符串）
    :return: API响应
    """
    client = JiKeYunAPIClient()
    return client.send_request(method, bizdata)
